use std::{
    cell::UnsafeCell,
    ops::{Deref, DerefMut},
};

mod test;

unsafe impl<T> Send for FreeLock<T> where T: ?Sized + Send {}
unsafe impl<T> Sync for FreeLock<T> where T: ?Sized + Send {}
unsafe impl<T> Sync for FreeLockGuard<'_, T> where T: ?Sized + Send + Sync {}

// FreeLock是一个无锁实现, 它允许同一时间可以持有一个对象的多个可变引用.
// 它的lock方法并不会有任何的互斥和阻塞操作.
pub struct FreeLock<T: ?Sized> {
    c: UnsafeCell<T>,
}

#[allow(dead_code)]
impl<T> FreeLock<T> {
    pub fn new(t: T) -> Self {
        FreeLock {
            c: UnsafeCell::new(t),
        }
    }

    pub fn lock(&self) -> FreeLockGuard<'_, T> {
        FreeLockGuard { guard: self }
    }

    pub fn into_inner(self) -> T {
        self.c.into_inner()
    }
}

pub struct FreeLockGuard<'a, T: ?Sized> {
    guard: &'a FreeLock<T>,
}

impl<'a, T> Deref for FreeLockGuard<'a, T> {
    type Target = T;
    fn deref(&self) -> &Self::Target {
        unsafe { &*self.guard.c.get() }
    }
}

impl<'a, T> DerefMut for FreeLockGuard<'a, T> {
    fn deref_mut(&mut self) -> &mut Self::Target {
        unsafe { &mut *self.guard.c.get() }
    }
}
